package com.vertx.starter;

import com.google.common.base.Preconditions;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.eventbus.DeliveryOptions;
import io.vertx.core.eventbus.Message;
import io.vertx.core.eventbus.MessageConsumer;

public class AppMessageSenderAgentImpl implements AppMessageSenderAgent {
    private final Vertx vertx;

    public void sendMessage(String address, Object payload) {
        this.checkPayloadType(payload, AppPayloadType.SEND);
        this.vertx.eventBus().send(address, payload);
    }

    public void sendMessage(String address, Object payload, DeliveryOptions options) {
        this.checkPayloadType(payload, AppPayloadType.SEND);
        this.vertx.eventBus().send(address, payload, options);
    }

    public void publishMessage(String address, Object payload) {
        this.checkPayloadType(payload, AppPayloadType.PUBLISH);
        this.vertx.eventBus().publish(address, payload);
    }

    public void publishMessage(String address, Object payload, DeliveryOptions options) {
        this.checkPayloadType(payload, AppPayloadType.PUBLISH);
        this.vertx.eventBus().publish(address, payload, options);
    }

    public <T> Future<Message<T>> requestMessage(String address, Object payload) {
        this.checkPayloadType(payload, AppPayloadType.REQUEST);
        return this.vertx.eventBus().request(address, payload);
    }

    public <T> Future<Message<T>> requestMessage(String address, Object payload, DeliveryOptions options) {
        this.checkPayloadType(payload, AppPayloadType.REQUEST);
        return this.vertx.eventBus().request(address, payload, options);
    }

    public <T> MessageConsumer<T> messageConsumer(String address, Handler<Message<T>> handler) {
        return this.vertx.eventBus().consumer(address, handler);
    }

    public <T> MessageConsumer<T> messageLocalConsumer(String address, Handler<Message<T>> handler) {
        return this.vertx.eventBus().localConsumer(address, handler);
    }

    private void checkPayloadType(Object payload, AppPayloadType targetType) {
        Class<?> clazz = payload.getClass();
        Preconditions.checkState(clazz.isAnnotationPresent(AppMessagePayloadMeta.class), "待发送消息的Payload必须声明注解AppMessagePayloadMeta!");
        AppMessagePayloadMeta meta = (AppMessagePayloadMeta) clazz.getAnnotation(AppMessagePayloadMeta.class);
        AppPayloadType actualType = meta.type();
        Preconditions.checkState(actualType == targetType, String.format("待发送消息的Payload的类型不正确!预期: %s 实际: %s", targetType, actualType));
    }

    public AppMessageSenderAgentImpl(Vertx vertx) {
        this.vertx = vertx;
    }
}
